/// created by hujintao
/// created at 2023/4/18
/// 描述:

// ignore_for_file: constant_identifier_names

import 'package:flutter/material.dart';

class HKCheckClick {
  static var lastPopTime = DateTime.now();
  static int needTime = 0;

  // 防重复提交
  static bool checkClick({int time = 1000}) {
    if (lastPopTime == null ||
        DateTime.now().difference(lastPopTime) >
            Duration(milliseconds: needTime)) {
      lastPopTime = DateTime.now();
      needTime = time;
      print("允许点击");
      return true;
    }
    print("请勿重复点击！");
    return false;
  }
}

const double _BFontSize = 16;
const Color _BTextColor = Colors.white;
const Color _BBackgroundColor = Color(0xFFED5130);
const FontWeight _BFontWeight = FontWeight.w500;
const double _BRadius = 6;
const double _BorderWidth = 1.0;

/// 通用按钮，支持用户设置背景色、是否可用等属性
///
/// [isEnable]如果设置为false，那么按钮呈现灰色态，点击事件不响应
///
/// 默认使用[Text]文本组件，如果用户想要显示其他组件。比如图片等，可以设置[child]属性
///
/// 文本组件需要的样式属性，可以通过[textStyle]设置，也可以通过[fontSize]等单独设置
///
/// 该组件的布局规则参考[Container]的布局规则
/// 该组件的[alignment]的属性默认为null,即使父布局给的约束是无边界(最大宽度或者最大高度是double.infinity.)
/// 组件的尺寸也会和child一样大。
/// 那就是说：不给[alignment]属性设置值，即使把[HKButton],放到[column]、[ListView]中，
/// 他也会尽可能的小。如果设置了[constraints]属性，那么就会按着[constraints]布局。
///
/// 案例一
/// ```dart
/// HKButton(
///    text: '主案特别长',
///    onTap: () {
///         ToastUtil.showToast(msg:'点击了主按钮');
///    },
/// )
/// ```
/// 按钮的大小就是text的大小+内边距的大小
///
/// 案例二
/// ```dart
/// HKButton(
///    constraints: BoxConstraints.expand(height: 60),
///    text: '主案特别长',
///    onTap: () {
///         ToastUtil.showToast(msg:'点击了主按钮');
///    },
/// )
/// ```
/// 按钮的大小：宽度充满父布局、高度是60
///
/// 如果给该组件的[alignment]赋值了，父布局的约束是有边界。
/// 该组件的尺寸就是父布局的约束， 并且会按着[alignment]属性来摆放[text]或者[child],比如居中摆放等.
///
/// 案例一
/// ```dart
/// HKButton(
///    alignment: Alignment.center,
///    text: '主案特别长',
///    onTap: () {
///         ToastUtil.showToast(msg:'点击了主按钮');
///    },
/// )
/// ```
/// 按钮的大小：宽度充满父布局  文字居中摆放
///
class HKButton extends StatefulWidget {
  /// 按钮是否可用 默认是true
  final bool isEnable;

  /// 按钮点击的回调
  final VoidCallback? onTap;

  /// 按钮显示的文案
  final String? text;

  /// 按钮的文字颜色 默认白色[_BTextColor]
  final Color textColor;

  /// 按钮的文字大小 默认[_BFontSize]
  final double fontSize;

  /// 按钮不可用的文字颜色
  final Color? disableTextColor;

  /// 按钮背景色 默认[_BBackgroundColor]
  final Color backgroundColor;

  /// 是否使用默认装饰器 默认[false]
  final bool? userDefaultDecoration;

  /// 按钮不可用背景色 默认[_BDisableBackgroundColor]
  final Color? disableBackgroundColor;

  /// 按钮内边距 默认水平[_BHorizontalPadding] 垂直[_BVerticalPadding]
  final EdgeInsetsGeometry padding;

  /// 按钮外边距 默认为0
  final EdgeInsetsGeometry? margin;

  /// 按钮的修饰 默认实色背景
  final Decoration? decoration;

  /// 防抖时间 单位毫秒 默认值1000毫秒
  final int? throttleDuration;

  /// 按钮的显示子节点 优先级高于[text]
  final Widget? child;

  /// 按钮的文本显示样式 优先级高于[textColor]等属性
  final TextStyle? textStyle;

  /// 按钮的文本Weight 默认是[FontWeight.bold]
  final FontWeight fontWeight;

  /// 按钮的布局约束 默认是自适应大小
  final BoxConstraints constraints;

  final double? width;
  final double? height;

  /// 是否使用InkWell 默认false
  final bool? isInkWell;

  /// inkWell长按手势
  final GestureLongPressCallback? onLongPress;

  /// 像素偏移
  final Matrix4? transform;

  /// 按钮的内部对齐 默认为null
  final Alignment? alignment;

  final HitTestBehavior? behavior;

  /// 按钮圆角大小
  final BorderRadiusGeometry borderRadius;

  const HKButton({
    Key? key,
    this.text = "",
    this.backgroundColor = _BBackgroundColor,
    this.isEnable = true,
    this.onTap,
    this.padding = EdgeInsets.zero,
    this.decoration,
    this.child,
    this.textStyle,
    this.fontWeight = _BFontWeight,
    this.fontSize = _BFontSize,
    this.textColor = _BTextColor,
    this.disableTextColor,
    this.disableBackgroundColor,
    this.constraints = const BoxConstraints.tightFor(),
    this.borderRadius = const BorderRadius.all(Radius.circular(_BRadius)),
    this.alignment,
    this.margin,
    this.throttleDuration,
    this.width,
    this.height,
    this.transform,
    this.isInkWell = false,
    this.behavior,
    this.onLongPress,
    this.userDefaultDecoration = false,
  }) : super(key: key);

  HKButton.outline({
    Key? key,
    Color? disableLineColor,
    Color? lineColor,
    double radius = _BRadius,
    double borderWith = _BorderWidth,
    required this.text,
    this.isEnable = true,
    this.backgroundColor = _BBackgroundColor,
    this.disableBackgroundColor,
    this.alignment,
    this.child,
    this.onTap,
    this.textColor = _BTextColor,
    this.fontWeight = _BFontWeight,
    this.fontSize = _BFontSize,
    this.disableTextColor,
    this.padding = EdgeInsets.zero,
    this.textStyle,
    this.margin,
    this.throttleDuration,
    this.constraints = const BoxConstraints.tightFor(),
    this.borderRadius = const BorderRadius.all(Radius.circular(_BRadius)),
    this.width,
    this.height,
    this.transform,
    this.isInkWell,
    this.behavior,
    this.onLongPress,
    this.userDefaultDecoration = false,
  })  : decoration = _OutlineBoxDecorationCreator.createOutlineBoxDecoration(
            isEnable: isEnable,
            disableBackgroundColor: disableBackgroundColor ??
                const Color(0xFFED5130).withOpacity(0.5),
            disableLineColor: disableLineColor,
            lineColor: lineColor,
            backgroundColor: backgroundColor,
            radius: radius,
            borderWith: borderWith),
        super(key: key);

  @override
  State<HKButton> createState() => _HKButtonState();
}

class _HKButtonState extends State<HKButton> {
  @override
  Widget build(BuildContext context) {
    if (widget.isInkWell == true) {
      return InkWell(
        onTap: () => _onTap(),
        onLongPress: widget.onLongPress,
        child: _buildBody(),
      );
    }
    return GestureDetector(
      onTap: () => _onTap(),
      behavior: widget.behavior,
      child: _buildBody(),
    );
  }

  TextStyle _getTextStyle() {
    if (widget.textStyle != null) {
      return widget.textStyle!;
    }
    Color textColor;
    if (widget.isEnable) {
      textColor = widget.textColor;
    } else {
      textColor =
          widget.disableTextColor ?? (widget.textColor).withOpacity(0.7);
    }

    return TextStyle(
      fontSize: widget.fontSize,
      color: textColor,
      fontWeight: widget.fontWeight,
    );
  }

  Color _getBackgroundColor() {
    return widget.isEnable
        ? widget.backgroundColor
        : widget.disableBackgroundColor ??
            const Color(0xFFED5130).withOpacity(0.5);
  }

  BoxDecoration _getBoxDecoration(Color? bgColor) {
    return BoxDecoration(
      color: bgColor,
      borderRadius: widget.borderRadius,
    );
  }

  _buildBody() {
    return Container(
      alignment: widget.alignment,
      decoration: widget.decoration ??
          (widget.userDefaultDecoration!
              ? _getBoxDecoration(_getBackgroundColor())
              : null),
      constraints: widget.constraints,
      padding: widget.padding,
      margin: widget.margin,
      width: widget.width,
      height: widget.height,
      transform: widget.transform,
      child: widget.child ??
          Text(
            widget.text ?? "",
            overflow: TextOverflow.ellipsis,
            maxLines: 1,
            style: _getTextStyle(),
          ),
    );
  }

  void _onTap() {
    if (widget.isEnable && widget.onTap != null) {
      /// 新增按钮防抖逻辑
      if (HKCheckClick.checkClick(time: widget.throttleDuration ?? 1000)) {
        widget.onTap!();
      }
    }
  }
}

class _OutlineBoxDecorationCreator {
  static BoxDecoration createOutlineBoxDecoration({
    required bool isEnable,
    Color? disableLineColor,
    Color? lineColor,
    required Color backgroundColor,
    required Color disableBackgroundColor,
    double radius = _BRadius,
    double borderWith = _BorderWidth,
  }) {
    Color _lineColor = isEnable ? lineColor! : disableLineColor!;
    Color _bgColor = isEnable ? backgroundColor : disableBackgroundColor;

    return BoxDecoration(
        border: Border.all(color: _lineColor, width: borderWith),
        borderRadius: BorderRadius.all(Radius.circular(radius)),
        color: _bgColor);
  }
}
